{
*******************************************************************************
-------------------------------------------------------------------------------
Kliper - next generation multimedia player
Copyright (C) Marcin 'vi4m' Kliks (vi4m@wp.pl)
Copyright (C) Tomasz 'dymsza' Odrobny (dymsza@gmail.com)
-------------------------------------------------------------------------------
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*******************************************************************************
}

unit settings;

interface


uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, ExtCtrls, Mask, IniFiles, engine, DrLabel,
  defaults, utils, StrUtils, Registry, ShlObj;

type
  Trestsetting = record
    sub_pos: integer;
  end;

type Tmpvideo_sound = record
    brightness: integer;
    contrast: Integer;
    hue: Integer;
    saturation: Integer;
  end;

type
  AString = array of string;

type
  Tsettingsform = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    PageControl1: TPageControl;
    TabSheet2: TTabSheet;
    GroupBox5: TGroupBox;
    Label2: TLabel;
    Label4: TLabel;
    videoout: TComboBox;
    doublebuffer: TCheckBox;
    rebuildindexcheck: TCheckBox;
    TabSheet3: TTabSheet;
    TabSheet4: TTabSheet;
    GroupBox3: TGroupBox;
    TabSheet5: TTabSheet;
    GroupBox2: TGroupBox;
    framedropcheck: TCheckBox;
    hardframedropcheck: TCheckBox;
    lowrescheck: TCheckBox;
    lowres: TComboBox;
    TabSheet6: TTabSheet;
    TabSheet7: TTabSheet;
    GroupBox1: TGroupBox;
    Label3: TLabel;
    fontsize: TComboBox;
    GroupBox4: TGroupBox;
    Label1: TLabel;
    Label5: TLabel;
    audioout: TComboBox;
    screensavercheck: TCheckBox;
    shutdowncheck: TCheckBox;
    TabSheet1: TTabSheet;
    GroupBox6: TGroupBox;
    langcombo: TComboBox;
    Label8: TLabel;
    GroupBox7: TGroupBox;
    dvdautodetectcheck: TCheckBox;
    drivecombo: TComboBox;
    Label9: TLabel;
    GroupBox8: TGroupBox;
    Label10: TLabel;
    cacheCombo: TComboBox;
    postprocessCheck: TCheckBox;
    GroupBox9: TGroupBox;
    chanfreqcombo: TComboBox;
    Label11: TLabel;
    Label12: TLabel;
    chancountcombo: TComboBox;
    Label14: TLabel;
    ppcombo: TComboBox;
    groupboxforfont: TGroupBox;
    FontDialog: TFontDialog;
    Label15: TLabel;
    ChangeSubFontButton: TButton;
    fontnamelabel: TLabel;
    fontsamplelabel: TDRLabel;
    TabSheet8: TTabSheet;
    GroupBox10: TGroupBox;
    GrayCheckBox: TCheckBox;
    FlipCheckBox: TCheckBox;
    MirrorCheckBox: TCheckBox;
    rotationBox: TCheckBox;
    rottation: TComboBox;
    fiterslist: TListBox;
    Label6: TLabel;
    Filtername: TLabel;
    rotationtype: TLabel;
    Timer1: TTimer;
    rgbtestbox: TCheckBox;
    TestChackBox: TCheckBox;
    GroupBox11: TGroupBox;
    hardwareEqualizer: TCheckBox;
    hwOptionLabel: TLabel;
    kliperSizeCheck: TCheckBox;
    Bevel1: TBevel;
    DrawBorder: TCheckBox;
    TabSheet9: TTabSheet;
    GB_Assocs: TGroupBox;
    PageControl2: TPageControl;
    TabSheet10: TTabSheet;
    TabSheet11: TTabSheet;
    B_None: TButton;
    B_All: TButton;
    LB_Assocs: TListBox;
    GB_AdditionalExts: TGroupBox;
    LB_AdditionalExts: TListBox;
    E_AdditionalExts: TEdit;
    B_AddExt: TButton;
    B_RemoveExt: TButton;
    I_FileIcon: TImage;
    TB_FileIcon: TTrackBar;
    L_FileIcon: TLabel;
    CB_AddOption: TCheckBox;
    CB_CheckAssocsAtStart: TCheckBox;
    LB_Assocs2: TListBox;
    CB_CheckAssocsAtStart2: TCheckBox;
    CB_AddOption2: TCheckBox;
    B_All2: TButton;
    B_None2: TButton;
    GB_AdditionalExts2: TGroupBox;
    LB_AdditionalExts2: TListBox;
    E_AdditionalExts2: TEdit;
    B_AddExt2: TButton;
    B_RemoveExt2: TButton;
    TB_FileIcon2: TTrackBar;
    L_FileIcon2: TLabel;
    I_FileIcon2: TImage;
    CB_RefreshAssocs: TCheckBox;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure writereadconfig(r_or_w: integer);
    procedure readconfig;
    procedure writeconfig;
    procedure getconfig;
    procedure FormShow(Sender: TObject);
    procedure ChangeSubFontButtonClick(Sender: TObject);
    procedure fiterslistClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure FormHide(Sender: TObject);
    procedure B_AddExtClick(Sender: TObject);
    procedure B_RemoveExtClick(Sender: TObject);
    procedure E_AdditionalExtsKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure B_AllClick(Sender: TObject);
    procedure B_NoneClick(Sender: TObject);
    procedure LB_AssocsClick(Sender: TObject);
    procedure TB_FileIconChange(Sender: TObject);
    procedure TB_FileIcon2Change(Sender: TObject);
    procedure LB_Assocs2Click(Sender: TObject);
    procedure B_All2Click(Sender: TObject);
    procedure B_None2Click(Sender: TObject);
    procedure E_AdditionalExts2KeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure B_AddExt2Click(Sender: TObject);
    procedure B_RemoveExt2Click(Sender: TObject);

  private
    colors_: Tmpvideo_sound;

    procedure PrepareInterface;
    function AddExtraOption(FileType: string): boolean;
    function CheckExt(Ext: string): boolean;
    { Private declarations }
  public
    config_file: string;
    AssociatedExtsVideo,
      AdditionalExtsVideo,
      NotAssociatedExtsVideo,
      AssociatedExtsAudio,
      AdditionalExtsAudio,
      NotAssociatedExtsAudio: string;
    procedure save_colors(kolory: Tmpvideo_sound);
    function load_colors: Tmpvideo_sound;
    function CaptureConsoleOutput(DosApp, rundir: string; AMemo: Tstringlist): string;

    function SearchFor(Text, ForWhat: string): integer;
    function SeparateExts(Exts: string): AString;
    procedure AssociateFiles(Refresh: boolean);
    procedure AssociateVideoFiles;
    procedure AssociateAudioFiles;
    { Public declarations }
  end;

const
  WR_WRITE = 1;
  WR_READ = 2;
  WR_DEFAULT = 3;

var
  settingsform: Tsettingsform;

procedure RestoreAssoc(Ext: string; Force: boolean = false); //te procke deklarujemy poza klasa, azeby
                                      //mozna bylo ja wywolac bez tworzenia formy
                                      //ustawien
procedure ClearRegistry; //ta tak samo...
function RemoveExtraOption(FileType: string): boolean; //to takze jest potrzebne

implementation
uses main, player;

{$R *.dfm}



function Tsettingsform.CaptureConsoleOutput(DosApp, rundir: string; AMemo: Tstringlist): string;
var

  temp: string;
const
  ReadBuffer = 1048576; // 1 MB Buffer
var
  Security: TSecurityAttributes;
  Readpipe, Writepipe: THandle;
  start: TStartUpInfo;
  ProcessInfo: TProcessInformation;
  Buffer: Pchar;
  TotalBytesRead,
    BytesRead: DWORD;
  Apprunning, n,
    BytesLeftThisMessage,
    TotalBytesAvail: integer;
begin
  with Security do
  begin
    nlength := SizeOf(TSecurityAttributes);
    binherithandle := true;
    lpsecuritydescriptor := nil;
  end;

  if Createpipe(Readpipe, Writepipe, @Security, 0) then
  begin
    // Redirect In- and Output through STARTUPINFO structure

    Buffer := AllocMem(ReadBuffer + 1);
    FillChar(Start, Sizeof(Start), #0);
    start.cb := SizeOf(start);
    start.hStdOutput := Writepipe;
    start.hStdInput := Readpipe;
    start.dwFlags := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW;
    start.wShowWindow := SW_HIDE;

    // Create a Console Child Process with redirected input and output

    if CreateProcess(nil, PChar(DosApp),
      @Security, @Security,
      true, CREATE_NO_WINDOW or NORMAL_PRIORITY_CLASS,
      nil, PChar(rundir),
      start, ProcessInfo) then
    begin
      n := 0;
      TotalBytesRead := 0;
      repeat
        // Increase counter to prevent an endless loop if the process is dead
        Inc(n, 1);

        // wait for end of child process
        Apprunning := WaitForSingleObject(ProcessInfo.hProcess, 100);
        Application.ProcessMessages;

        // it is important to read from time to time the output information
        // so that the pipe is not blocked by an overflow. New information
        // can be written from the console app to the pipe only if there is
        // enough buffer space.

        if not PeekNamedpipe(Readpipe, @Buffer[TotalBytesRead],
          ReadBuffer, @BytesRead,
          @TotalBytesAvail, @BytesLeftThisMessage) then break
        else if BytesRead > 0 then
          ReadFile(Readpipe, Buffer[TotalBytesRead], BytesRead, BytesRead, nil);
        TotalBytesRead := TotalBytesRead + BytesRead;
      until (Apprunning <> WAIT_TIMEOUT) or (n > 150);

      Buffer[TotalBytesRead] := #0;
      OemToChar(Buffer, Buffer);
      AMemo.Text := AMemo.text + StrPas(Buffer);
    end;
    FreeMem(Buffer);
    CloseHandle(ProcessInfo.hProcess);
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(Readpipe);
    CloseHandle(Writepipe);
  end;
  Result := temp;
end;


function readwrite_bool(header, title: string; variable, default: boolean; wr: integer;
  config_: tinifile): boolean;
begin
  case wr of
    WR_WRITE: begin
        config_.WriteBool(header, title, variable);
        result := variable;
      end;
    WR_READ: result := config_.readbool(header, title, default);
    WR_DEFAULT: result := default;

  end;

end;







function readwrite_integer(header, title: string; variable, default: integer;
  wr: integer; config_: tinifile): integer;
begin
  case wr of
    WR_WRITE: begin
        config_.Writeinteger(header, title, variable);
        result := variable;
      end;
    WR_READ: result := config_.readinteger(header, title, default);
    WR_DEFAULT: result := default;
  end;
end;



function readwrite_string(header, title: string; variable, default: string;
  wr: integer; config_: tinifile): string;
begin
  case wr of
    WR_WRITE: begin
        config_.WriteString(header, title, variable);
        result := variable;
      end;
    WR_READ: result := config_.ReadString(header, title, default);
    WR_DEFAULT: result := default;

  end;

end;

function Tsettingsform.SearchFor(Text, ForWhat: string): integer;
//funkcja zwraca nam liczbe danych znakow w stringu
var
  i,
    counter: integer;
begin
  counter := 0;
  for i := 1 to Length(Text) do
  begin
    if Copy(Text, i, Length(ForWhat)) = ForWhat then
      counter := counter + 1;
  end;
  result := counter;
end;

function Tsettingsform.SeparateExts(Exts: string): AString;
//funkcja dzieli rozszerzenia ze stringa na tablice
var
  s: string;
  i,
    count: integer;
begin
  s := Exts;
  count := SearchFor(s, ';');

  SetLength(result, count);
  for i := 0 to count - 1 do
  begin
    result[i] := Copy(s, 1, Pos(';', s) - 1);

    s := Copy(s, Pos(';', s) + 1, Length(s) - Pos(';', s));
  end;
end;

function Tsettingsform.CheckExt(Ext: string): boolean;
//funkcja sprawdza czy podany ext juz gdzies nie wystepuje na listach
//lub czy nie jest 'zakazany'
var
  i: integer;
begin
  result := true;

  for i := 0 to LB_Assocs.Count - 1 do
  begin
    if Ext = LB_Assocs.Items.Strings[i] then
      result := false;
  end;

  for i := 0 to LB_Assocs2.Count - 1 do
  begin
    if Ext = LB_Assocs2.Items.Strings[i] then
      result := false;
  end;

  for i := 0 to LB_AdditionalExts2.Count - 1 do
  begin
    if LB_AdditionalExts2.Items.Strings[i] = Ext then
      result := false;
  end;

  for i := 0 to LB_AdditionalExts.Count - 1 do
  begin
    if LB_AdditionalExts.Items.Strings[i] = Ext then
      result := false;
  end;

  if (Ext = '') or (Ext = 'exe') or
    (Ext = 'com') or (Ext = 'dll') or
    (Ext = 'sys') or (Ext = 'drv') or
    (Pos(Ext, ' ') > 0) then //mozna by wymieniac w nieskonczonosc 'zakazane' rozszerzenia...
  begin
    result := false;
  end;
end;

function Tsettingsform.AddExtraOption(FileType: string): boolean;
//funkcja dodaje do podanego typu pliku akcje 'otworz w kliperze'
//(na podstawie sciezki do aktualnie uruchomionego pliku exe programu)
var
  r: TRegistry;
begin
  result := true;

  if (FileType = '') or (FileType = reg_file_type_video) or
    (FileType = reg_file_type_audio) then
  begin
    result := false;
    Exit;
  end;

  r := TRegistry.Create;

  try
    r.RootKey := HKEY_CLASSES_ROOT;

    if r.KeyExists(FileType) then
    begin
      r.OpenKey(FileType + '\\shell\\' + reg_open_with_kliper, true);
      r.WriteString('', translatestr('KTS_OPEN_WITH_KLIPER'));
      r.CloseKey;

      r.OpenKey(FileType + '\\shell\\' + reg_open_with_kliper + '\\command', true);
      r.WriteString('', '"' + paramstr(0) + '" "%1"');
      r.CloseKey;
    end;
  except
    result := false;
  end;

  r.Free;
end;

function RemoveExtraOption(FileType: string): boolean;
//funkcja usuwa z podanego typu pliku akcje 'otworz w kliperze'
var
  r: TRegistry;
begin
  result := true;

  if (FileType = '') or (FileType = reg_file_type_video) or
    (FileType = reg_file_type_audio) then
  begin
    result := false;
    Exit;
  end;

  r := TRegistry.Create;

  try
    r.RootKey := HKEY_CLASSES_ROOT;
    r.DeleteKey(FileType + '\\shell\\' + reg_open_with_kliper);

    r.CloseKey;
  except
    result := false;
  end;

  r.Free;
end;

procedure Tsettingsform.AssociateFiles(Refresh: boolean);
//glowna procedurka wywolywana jak chcemy powiazac pliki
begin
  settingsform.AssociateVideoFiles;
  settingsform.AssociateAudioFiles;

  if Refresh then
    SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
end;

procedure Tsettingsform.AssociateVideoFiles;
//wiaze (lub odwiazuje) pliki wideo
var
  r: TRegistry;
  i: integer;
  old: string;
  exts: AString;
begin
  r := TRegistry.Create;

  try
    r.RootKey := HKEY_CLASSES_ROOT;


    r.OpenKey(reg_file_type_video, true);
    r.WriteString('', translatestr('KTS_FILETYPE_VIDEO'));
    r.CloseKey;
    r.OpenKey(reg_file_type_video + '\\DefaultIcon', true);
    r.WriteString('', paramstr(0) + ',' + inttostr(TB_FileIcon.Position + 1));
    r.CloseKey;
    r.OpenKey(reg_file_type_video + '\\shell\\open\\command', true);
    r.WriteString('', '"' + paramstr(0) + '" "%1"');
    r.CloseKey;

    exts := SeparateExts(LowerCase(AssociatedExtsVideo) + LowerCase(AdditionalExtsVideo));

    //przywiazujemy ext do klipera
    for i := 0 to Length(exts) - 1 do
    begin
      r.OpenKey('.' + exts[i], true);
      old := r.ReadString('');

      if old <> reg_file_type_video then
      begin
        r.WriteString(reg_backup, old);

        r.WriteString('', reg_file_type_video);
      end;

      r.CloseKey
    end;

    //i odwiazujemy te ktorych user juz nie chce
    exts := SeparateExts(LowerCase(NotAssociatedExtsVideo));
    for i := 0 to Length(exts) - 1 do
    begin
      RestoreAssoc(exts[i]);

      r.OpenKey('.' + exts[i], true);
      old := r.ReadString('');

      if CB_AddOption.Checked then //jesli mamy dodac opcje 'otworz w kliper'
      begin //to dodajemy
        if (old = '') or (old = reg_file_type_video) then
          AddExtraOption(r.ReadString(''))
        else
          AddExtraOption(old);
      end
      else //jesli nie, to upewniamy sie ze jej nie bedzie
      begin //czyli probojemy usunac :)
        if (old = '') or (old = reg_file_type_video) then
          RemoveExtraOption(r.ReadString(''))
        else
          RemoveExtraOption(old);
      end;

      r.CloseKey
    end;
  except
    //just do nothing...
  end;

  r.Free;
end;

procedure Tsettingsform.AssociateAudioFiles;
//a tutaj lustrzana procka dla plikow audio
var
  r: TRegistry;
  i: integer;
  old: string;
  exts: AString;
begin
  r := TRegistry.Create;

  try
    r.RootKey := HKEY_CLASSES_ROOT;


    r.OpenKey(reg_file_type_audio, true);
    r.WriteString('', translatestr('KTS_FILETYPE_AUDIO'));
    r.CloseKey;
    r.OpenKey(reg_file_type_audio + '\\DefaultIcon', true);
    r.WriteString('', paramstr(0) + ',' + inttostr(TB_FileIcon2.Position + 1));
    r.CloseKey;
    r.OpenKey(reg_file_type_audio + '\\shell\\open\\command', true);
    r.WriteString('', '"' + paramstr(0) + '" "%1"');
    r.CloseKey;

    exts := SeparateExts(LowerCase(AssociatedExtsAudio) + LowerCase(AdditionalExtsAudio));

    //przywiazujemy ext do klipera
    for i := 0 to Length(exts) - 1 do
    begin
      r.OpenKey('.' + exts[i], true);
      old := r.ReadString('');

      if old <> reg_file_type_audio then
      begin
        r.WriteString(reg_backup, old);

        r.WriteString('', reg_file_type_audio);
      end;

      r.CloseKey
    end;

    //i odwiazujemy te ktorych user juz nie chce
    exts := SeparateExts(LowerCase(NotAssociatedExtsAudio));
    for i := 0 to Length(exts) - 1 do
    begin
      RestoreAssoc(exts[i]);

      r.OpenKey('.' + exts[i], true);
      old := r.ReadString('');

      if CB_AddOption2.Checked then //jesli mamy dodac opcje 'otworz w kliper'
      begin //to dodajemy
        if (old = '') or (old = reg_file_type_audio) then
          AddExtraOption(r.ReadString(''))
        else
          AddExtraOption(old);
      end
      else //jesli nie, to upewniamy sie ze jej nie bedzie
      begin //czyli probojemy usunac :)
        if (old = '') or (old = reg_file_type_audio) then
          RemoveExtraOption(r.ReadString(''))
        else
          RemoveExtraOption(old);
      end;

      r.CloseKey
    end;
  except
    //just do nothing...
  end;

  r.Free;
end;

procedure RestoreAssoc(Ext: string; Force: boolean = false);
var
  r: TRegistry;
  old: string;
begin
  r := TRegistry.Create;

  try
    r.RootKey := HKEY_CLASSES_ROOT; //troche to kijowo jest zrobione
                                            //bo jesli usunie sie Kliper.Backup
    r.OpenKey('.' + Ext, true); //to po odwiazaniu nic niezostanie
    old := r.ReadString(reg_backup); //wpisane, ale inaczej nie idzie zrobic
                                            // :/
    if r.ValueExists(reg_backup) then
      r.WriteString('', old);

    if (Force) and ((r.ReadString('') = reg_file_type_video) or
      (r.ReadString('') = reg_file_type_audio)) then
      r.WriteString('', old);

    r.DeleteValue(reg_backup);

    r.CloseKey;
  except
    //
  end;

  r.Free;
end;

procedure ClearRegistry;
var
  i: integer;
  s,
    add_video,
    add_audio: string;
  tmp: AString;
  cfg: TINIFile;
  r: TRegistry;
begin
  //zczytujemy z configa dodatkowe roszszerzenia
  cfg := TINIFile.Create(extractfiledir(paramstr(0)) + '\config.ini');
  add_video := cfg.ReadString('assocations', 'additionalvideo', '');
  add_audio := cfg.ReadString('assocations', 'additionalaudio', '');
  cfg.Free; //i zwalniamy

  r := TRegistry.Create;
  r.RootKey := HKEY_CLASSES_ROOT;

  s := movie_filter + ';';
  s := StringReplace(s, '*.', '', [rfReplaceAll]);
  s := StringReplace(s, '|', '', [rfReplaceAll]);


  tmp := settingsform.SeparateExts(s + add_video);

  for i := 0 to Length(tmp) - 1 do
  begin
    RestoreAssoc(tmp[i], true); //przywracamy skojarzenie

    r.OpenKey('.' + tmp[i], false);
    RemoveExtraOption(r.ReadString('')); //i usuwamy ewentualna opcje 'otworz z kliperem'
    r.CloseKey;
  end;

  s := audio_filter + ';';
  s := StringReplace(s, '*.', '', [rfReplaceAll]);
  s := StringReplace(s, '|', '', [rfReplaceAll]);

  tmp := settingsform.SeparateExts(s + add_audio);

  for i := 0 to Length(tmp) - 1 do
  begin
    RestoreAssoc(tmp[i], true); //tu podobnie jak wyzej...

    r.OpenKey('.' + tmp[i], false);
    RemoveExtraOption(r.ReadString(''));
    r.CloseKey;
  end;

  r.DeleteKey(reg_file_type_video); //i usuwamy typ pliku klipera
  r.DeleteKey(reg_file_type_audio);

  r.Free;

  //i na koncu odswiezamy
  SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nil, nil);
end;

procedure Tsettingsform.PrepareInterface;
var
  i: integer;
  tmp: AString;
  s: string;
begin
  //przygorowujemy interfejs dla kart wideo...
  s := movie_filter + ';';
  s := StringReplace(s, '*.', '', [rfReplaceAll]);
  s := StringReplace(s, '|', '', [rfReplaceAll]);

  tmp := SeparateExts(s);

  LB_Assocs.Clear;
  for i := 0 to Length(tmp) - 1 do
  begin
    LB_Assocs.Items.Add(tmp[i]);
  end;
  LB_Assocs.Sorted := true;

  tmp := SeparateExts(AssociatedExtsVideo);
  for i := 0 to Length(tmp) - 1 do
  begin
    if LB_Assocs.Items.IndexOf(tmp[i]) <> -1 then
      LB_Assocs.Selected[LB_Assocs.Items.IndexOf(tmp[i])] := true;
  end;

  NotAssociatedExtsVideo := '';
  for i := 0 to LB_Assocs.Count - 1 do
  begin
    if not LB_Assocs.Selected[i] then
    begin
      NotAssociatedExtsVideo := NotAssociatedExtsVideo + LB_Assocs.Items.Strings[i] + ';';
    end;
  end;

  LB_AdditionalExts.Clear;
  tmp := SeparateExts(AdditionalExtsVideo);
  for i := 0 to Length(tmp) - 1 do
  begin
    LB_AdditionalExts.Items.Add(tmp[i]);
  end;

  //...i dla karty audio
  s := audio_filter + ';';
  s := StringReplace(s, '*.', '', [rfReplaceAll]);
  s := StringReplace(s, '|', '', [rfReplaceAll]);

  tmp := SeparateExts(s);

  LB_Assocs2.Clear;
  for i := 0 to Length(tmp) - 1 do
  begin
    LB_Assocs2.Items.Add(tmp[i]);
  end;
  LB_Assocs2.Sorted := true;

  tmp := SeparateExts(AssociatedExtsAudio);
  for i := 0 to Length(tmp) - 1 do
  begin
    if LB_Assocs2.Items.IndexOf(tmp[i]) <> -1 then
      LB_Assocs2.Selected[LB_Assocs2.Items.IndexOf(tmp[i])] := true;
  end;

  NotAssociatedExtsAudio := '';
  for i := 0 to LB_Assocs2.Count - 1 do
  begin
    if not LB_Assocs2.Selected[i] then
    begin
      NotAssociatedExtsAudio := NotAssociatedExtsAudio + LB_Assocs2.Items.Strings[i] + ';';
    end;
  end;

  LB_AdditionalExts2.Clear;
  tmp := SeparateExts(AdditionalExtsAudio);
  for i := 0 to Length(tmp) - 1 do
  begin
    LB_AdditionalExts2.Items.Add(tmp[i]);
  end;
end;

function Tsettingsform.load_colors: Tmpvideo_sound;

begin
  Result := colors_;
end;

procedure Tsettingsform.save_colors(kolory: Tmpvideo_sound);


begin
  colors_.brightness := kolory.brightness;
  colors_.contrast := kolory.contrast;
  colors_.saturation := kolory.saturation;
  colors_.hue := kolory.hue;
end;



procedure Tsettingsform.writereadconfig(r_or_w: integer);

var
  config: tinifile;
  f: tfont;

begin
  try

    config := TIniFile.Create(extractfiledir(paramstr(0)) + '\config.ini');
    settingsform.kliperSizeCheck.Checked := readwrite_bool('video', 'kliperSize', settingsform.kliperSizeCheck.Checked, false, r_or_w, config);
///=========================================video=========================////
    settingsform.videoout.ItemIndex := readwrite_integer('video', 'out',
      settingsform.videoout.ItemIndex, 0, r_or_w, config);
    settingsform.hardwareEqualizer.Checked := readwrite_bool('performance', 'useHardwareEqualizer', hardwareEqualizer.Checked, true, r_or_w, config);
    settingsform.cacheCombo.Text := inttostr(readwrite_integer('network', 'cache_size',
      strtoint(settingsform.cacheCombo.text), 1000, r_or_w, config));
    doublebuffer.Checked := readwrite_bool('video', 'double',
      doublebuffer.Checked, false, r_or_w, config);
    rebuildindexcheck.Checked := readwrite_bool('video', 'rebuildindexcheck',
      rebuildindexcheck.Checked, true, r_or_w, config);
    postprocessCheck.Checked := readwrite_bool('video', 'postprocess',
      postprocessCheck.Checked, false, r_or_w, config);
    ppcombo.ItemIndex := readwrite_integer('video', 'postprocess_level',
      ppcombo.ItemIndex, 0, r_or_w, config);
    screensavercheck.Checked := readwrite_bool('video', 'screensaver',
      screensavercheck.Checked, true, r_or_w, config);
    shutdowncheck.Checked := readwrite_bool('video', 'shutdown',
      shutdowncheck.Checked, false, r_or_w, config);
///=========================================audio=========================////
    audioout.ItemIndex := readwrite_integer('audio', 'out',
      settingsform.audioout.ItemIndex, 0, r_or_w, config);
    chanfreqcombo.ItemIndex := readwrite_integer('audio', 'fqr',
      chanfreqcombo.ItemIndex, 0, r_or_w, config);
    chancountcombo.ItemIndex := readwrite_integer('audio', 'chanal',
      chancountcombo.ItemIndex, 0, r_or_w, config);
    mainform.volbar.Position := readwrite_integer('audio', 'volume', mainform.volbar.Position, 70, r_or_w, config);

///===============================wydajnosc========================================//
    framedropcheck.Checked := readwrite_bool('wydajnosc', 'use_framedrop',
      framedropcheck.Checked, true, r_or_w, config);
    hardframedropcheck.Checked := readwrite_bool('wydajnosc', 'use_hardframedrop',
      hardframedropcheck.Checked, false, r_or_w, config);
    lowrescheck.Checked := readwrite_bool('wydajnosc', 'use_lores',
      lowrescheck.Checked, false, r_or_w, config);
    lowres.ItemIndex := readwrite_integer('wydajnosc', 'lores',
      chancountcombo.ItemIndex, 0, r_or_w, config);

    hardwareEqualizer.checked := readwrite_bool('wydajnosc', 'hardwareEqualizer',
      hardwareEqualizer.checked, false, r_or_w, config);

    mainform.paski[3].enabled := hardwareEqualizer.checked;
    mainform.paski[2].enabled := hardwareEqualizer.checked;

////===========================dvd=================================================//
    dvdautodetectcheck.Checked := readwrite_bool('dvd', 'autodetect',
      dvdautodetectcheck.Checked, true, r_or_w, config);
    drivecombo.ItemIndex := readwrite_integer('dvd', 'device',
      drivecombo.ItemIndex, 0, r_or_w, config);
////===========================filtry============================================//
    GrayCheckBox.Checked := readwrite_bool('filtry', 'gray',
      GrayCheckBox.Checked, false, r_or_w, config);
    FlipCheckBox.Checked := readwrite_bool('filtry', 'flip',
      FlipCheckBox.Checked, false, r_or_w, config);
    MirrorCheckBox.Checked := readwrite_bool('filtry', 'Mirro',
      MirrorCheckBox.Checked, false, r_or_w, config);

    rotationBox.Checked := readwrite_bool('filtry', 'rotation',
      rotationBox.Checked, false, r_or_w, config);
    rottation.ItemIndex := readwrite_integer('filtry', 'rotation_type',
      rottation.ItemIndex, 0, r_or_w, config);
    rgbtestbox.Checked := readwrite_bool('filtry', 'rgbtest_',
      rgbtestbox.Checked, false, r_or_w, config);
    TestChackBox.Checked := readwrite_bool('filtry', 'test',
      TestChackBox.Checked, false, r_or_w, config);
    if postprocessCheck.Checked then
      sets.filters.postprocessing := ppcombo.ItemIndex;
//fonty///////////////////////////////////////////////////////////////////////

    langCombo.ItemIndex := langcombo.Items.IndexOf(readwrite_string('main', 'lang', langCombo.text, kliper_default_lang, r_or_w, config));
    f := tfont.create;
    fontnamelabel.Caption := readwrite_string('subtitles', 'font', fontnamelabel.Caption, '"Arial", 20, [], [clWhite]', r_or_w, config);
    stringtofont(fontnamelabel.caption, f);
    fontsamplelabel.Font := f;

    DrawBorder.Checked := readwrite_bool('subtitles', 'drawborder',
      DrawBorder.Checked, true, r_or_w, config);

{==============================skojarzenia============================}
    CB_RefreshAssocs.Checked := readwrite_bool('assocations', 'refresh',
      CB_RefreshAssocs.Checked, false, r_or_w, config);

    CB_CheckAssocsAtStart.Checked := readwrite_bool('assocations', 'checkatstartvideo',
      CB_CheckAssocsAtStart.Checked, false, r_or_w, config);
    CB_AddOption.Checked := readwrite_bool('assocations', 'addoptionvideo',
      CB_AddOption.Checked, false, r_or_w, config);
    AssociatedExtsVideo := readwrite_string('assocations', 'extsvideo',
      AssociatedExtsVideo, '', r_or_w, config);
    AdditionalExtsVideo := readwrite_string('assocations', 'additionalvideo',
      AdditionalExtsVideo, '', r_or_w, config);
    TB_FileIcon.Position := readwrite_integer('assocations', 'videofileicon',
      TB_FileIcon.Position, 8, r_or_w, config);

    CB_CheckAssocsAtStart2.Checked := readwrite_bool('assocations', 'checkatstartaudio',
      CB_CheckAssocsAtStart2.Checked, false, r_or_w, config);
    CB_AddOption2.Checked := readwrite_bool('assocations', 'addoptionaudio',
      CB_AddOption2.Checked, false, r_or_w, config);
    AssociatedExtsAudio := readwrite_string('assocations', 'extsaudio',
      AssociatedExtsAudio, '', r_or_w, config);
    AdditionalExtsAudio := readwrite_string('assocations', 'additionalaudio',
      AdditionalExtsAudio, '', r_or_w, config);
    TB_FileIcon2.Position := readwrite_integer('assocations', 'audiofileicon',
      TB_FileIcon2.Position, 7, r_or_w, config);

//////////////////////////KOLORY ////////////////////////////////////////////


    mainform.paski[0].pos := readwrite_integer('COLORS', 'brightness', mainform.paski[0].pos, 0, r_or_w, config);
    mainform.paski[1].pos := readwrite_integer('COLORS', 'contrast', mainform.paski[1].pos, 0, r_or_w, config);
    mainform.paski[2].pos := readwrite_integer('COLORS', 'hue', mainform.paski[2].pos, 0, r_or_w, config);
    mainform.paski[3].pos := readwrite_integer('COLORS', 'saturation', mainform.paski[3].pos, 0, r_or_w, config);




    ppcombo.Items.Clear;
    ppcombo.Items.Append(translatestr('KTS_GENERIC_PP_1'));
    ppcombo.Items.Append(translatestr('KTS_GENERIC_PP_2'));
    ppcombo.Items.Append(translatestr('KTS_GENERIC_PP_3'));
    ppcombo.Items.Append(translatestr('KTS_GENERIC_PP_4'));
    ppcombo.Items.Append(translatestr('KTS_GENERIC_PP_5'));
    ppcombo.ItemIndex := sets.filters.postprocessing;

    fontsamplelabel.Caption := translatestr('KTS_GENERIC_FONTSAMPLETEXT');

    mainform.sublabel.DrawBorder := DrawBorder.Checked;

  finally
    f.free;
    config.UpdateFile;
    config.Free;
  end;
end;







procedure Tsettingsform.getconfig;
var // f:tfont;
  x: integer;
  s: integer;
begin
//auto konfig ////////////////
  sets.font_patch := extractfiledir(paramstr(0)) + '\fonts\arial-' +
    settingsform.fontsize.Text + '\font.desc';
  sets.hwEqualizer := hardwareEqualizer.checked;

/////video///////////////////////////////////////
  sets.video_out := videoout.Text;
  if postprocessCheck.Checked then
    sets.filters.postprocessing := ppcombo.ItemIndex + 1 else
    sets.filters.postprocessing := 0;


  sets.doublebuffer := doublebuffer.Checked;
  sets.rebuild_index := rebuildindexcheck.checked;
/////audio///////////////////////////
  sets.audio_out := audioout.Text;
  if (chanfreqcombo.ItemIndex > 0) then sets.srate := StrToInt(chanfreqcombo.Text);
  if (chancountcombo.ItemIndex > 0) then sets.channels := StrToInt(chancountcombo.Text);
/////////////////////////////////////// wydajnos////////
  sets.framedrop := framedropcheck.Checked;
  sets.hardframedrop := hardframedropcheck.Checked;
  if lowrescheck.Checked then sets.lowres := lowres.ItemIndex + 1 else
    sets.lowres := 0;
////===========================filtry============================================//
  sets.filters.gray := GrayCheckBox.Checked;
  sets.filters.flip := FlipCheckBox.Checked;
  sets.filters.mirror := MirrorCheckBox.Checked;
  sets.filters.rgbtest := rgbtestbox.Checked;
  sets.filters.test := TestChackBox.Checked;

  if (rottation.ItemIndex >= 0) and (rotationBox.Checked) then
    sets.filters.rotate := rottation.ItemIndex else sets.filters.rotate := -1;


  //setting subtitle font to choosen one
  main.mainform.setsubfont(fontnamelabel.Caption);

  if screensavercheck.Checked then Application.OnMessage := mainform.AppMessage
  else application.OnMessage := nil;
  val(cachecombo.text, x, s);
  sets.URL_cache := x;
end;

procedure Tsettingsform.Button1Click(Sender: TObject);
begin
  settingsform.readconfig;
  close;
end;

procedure Tsettingsform.Button2Click(Sender: TObject);
begin
  settingsform.writeconfig;
  settingsform.getconfig;
  kplayer.engine.setconfig(main.sets);
  main.mainform.updateLanguage;

  settingsform.AssociateFiles(CB_RefreshAssocs.Checked);

  close;
end;

procedure Tsettingsform.FormCreate(Sender: TObject);
begin
  langCombo.Items := findfiles(extractfiledir(paramstr(0)) + '\lang\', '*.lang');
  fontnamelabel.caption := fonttostring(fontsamplelabel.font);
  hide;
  {
  SetWindowPos(
    Handle,
    HWND_TOPMOST,
    0,
    0,
    0,
    0,
    SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
    }
end;

procedure Tsettingsform.FormShow(Sender: TObject);
begin

  timer1.Enabled := true;
  settingsform.writeconfig;
  settingsform.readconfig;
  pagecontrol1.ActivePageIndex := 0;
  Pagecontrol1.ActivePageIndex := 1;

  settingsform.PrepareInterface;
end;

procedure Tsettingsform.ChangeSubFontButtonClick(Sender: TObject);
begin
  fontdialog.Font := fontsamplelabel.Font;
  if fontdialog.Execute then begin
    fontsamplelabel.Font := fontdialog.Font;
    mainform.subLabel.Font := fontdialog.Font;
    fontnamelabel.Caption := FontToString(fontdialog.font);
    writeconfig;
  end;

end;

//wrapper around wrconfig, for convienience

procedure Tsettingsform.readconfig;
begin
  writereadconfig(settings.WR_READ);
end;

//wrapper around wrconfig, for convienience

procedure Tsettingsform.writeconfig;
begin
  writereadconfig(settings.WR_WRITE);
end;

procedure Tsettingsform.fiterslistClick(Sender: TObject);
  procedure hideall;
  begin
    GrayCheckBox.Visible := False;
    FlipCheckBox.Visible := False;
    MirrorCheckBox.Visible := False;
    rotationBox.Visible := FALSE;
    rottation.Visible := False;
    rotationtype.Visible := False;
    rgbtestbox.Visible := False;
    TestChackBox.Visible := False;
  end;

begin

//jest to tak nie inaczej aby bylo uniwersalniej gdyb zmienila sie kolejnosc nie ebdzie czba zminiac nic
  if fiterslist.Items.Strings[fiterslist.ItemIndex] = 'Flip' then
  begin
    Filtername.Caption := translatestr('KTS_FILTERS_FLIP_SCREEN');
    hideall;
    FlipCheckBox.Visible := True;
  end;

  if fiterslist.Items.Strings[fiterslist.ItemIndex] = 'Gray' then
  begin
    Filtername.Caption := translatestr('KTS_FILTERS_GRAYSCALE');
    hideall;
    GrayCheckBox.Visible := True;

  end;

{
IF fiterslist.Items.Strings[fiterslist.ItemIndex]='Gray' then
begin
Filtername.Caption:= 'Skala szarosci';
hideall;
GrayCheckBox.Visible:=True;

end;
}

  if fiterslist.Items.Strings[fiterslist.ItemIndex] = 'Mirror' then
  begin
    Filtername.Caption := translatestr('KTS_FILTERS_MIRROR');
    hideall;
    MirrorCheckBox.Visible := True;

  end;

  if fiterslist.Items.Strings[fiterslist.ItemIndex] = 'Rotation' then
  begin
    Filtername.Caption := translatestr('KTS_FILTERS_ROTATE');
    hideall;
    rotationBox.Visible := True;
    rottation.Visible := True;
    rotationtype.Visible := True;
  end;

  if fiterslist.Items.Strings[fiterslist.ItemIndex] = 'RgbTest' then
  begin
    Filtername.Caption := translatestr('KTS_FILTERS_RGBTEST');
    hideall;
    rgbtestbox.Visible := True;
  end;

  if fiterslist.Items.Strings[fiterslist.ItemIndex] = 'Test' then
  begin
    Filtername.Caption := translatestr('KTS_FILTERS_TEST');
    hideall;
    TestChackBox.Visible := True;
  end;

end;

procedure Tsettingsform.Timer1Timer(Sender: TObject);
begin
  if rotationBox.Checked then
    rottation.Enabled := True else rottation.Enabled := false;

  if postprocessCheck.Checked then ppcombo.Enabled := True else
    ppcombo.Enabled := false;
end;

procedure Tsettingsform.Button3Click(Sender: TObject);
begin
  writereadconfig(WR_DEFAULT);
end;

procedure Tsettingsform.Button4Click(Sender: TObject);
var l: tstringlist;
begin
  l := tstringlist.Create;
  captureconsoleoutput(extractfiledir(paramstr(0)) + '\enum.exe', extractfiledir(paramstr(0)), l);

end;

procedure Tsettingsform.FormHide(Sender: TObject);
begin
  timer1.Enabled := false;
end;

procedure Tsettingsform.B_AddExtClick(Sender: TObject);
var
  i: integer;
begin
  //spr. czy mozne dodac
  if settingsform.CheckExt(E_AdditionalExts.Text) = false then
  begin
    E_AdditionalExts.Text := '';
    Exit;
  end;

  //jesli tak to dodajemy do listy
  //i odswiezamy ja
  LB_AdditionalExts.Items.Add(LowerCase(E_AdditionalExts.Text));
  AdditionalExtsVideo := '';
  for i := 0 to LB_AdditionalExts.Count - 1 do
  begin
    AdditionalExtsVideo := AdditionalExtsVideo + LB_AdditionalExts.Items.Strings[i] + ';';
  end;
  E_AdditionalExts.Text := '';
end;

procedure Tsettingsform.B_RemoveExtClick(Sender: TObject);
//tutaj gdyt user usuwa dodatkowe rozszerzenie z listy zostaje ono automatycznie
//odwiazane od klipera

//wiem, troche kojowe to rozwiazanie, ale tylko to mi przyszlo do glowy :/
var
  i: integer;
begin
  if LB_AdditionalExts.ItemIndex <> -1 then
  begin
    //odwiazujemy
    RestoreAssoc(LB_AdditionalExts.Items.Strings[LB_AdditionalExts.ItemIndex]);
    //i usuwamy z listy
    LB_AdditionalExts.Items.Delete(LB_AdditionalExts.ItemIndex);
  end;

  //odswiezamy liste dodatkowych rozszerzen
  AdditionalExtsVideo := '';
  for i := 0 to LB_AdditionalExts.Count - 1 do
  begin
    AdditionalExtsVideo := AdditionalExtsVideo + LB_AdditionalExts.Items.Strings[i] + ';';
  end;
end;

procedure Tsettingsform.E_AdditionalExtsKeyDown(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin
  //tutaj dorobilem obsluge entera w polu dodawania exta
  //praktyczniej...
  if Key = VK_RETURN then
  begin
    B_AddExt.Click;
  end;
end;

procedure Tsettingsform.B_AllClick(Sender: TObject);
begin
  //wybieramy wsio z listy wideo
  LB_Assocs.SelectAll;
  //i powiazujemy
  LB_AssocsClick(LB_Assocs);
end;

procedure Tsettingsform.B_NoneClick(Sender: TObject);
begin
  //pozbywamy sie wszystkich skojarzen
  LB_Assocs.ClearSelection;
  LB_AssocsClick(LB_Assocs);
end;

procedure Tsettingsform.LB_AssocsClick(Sender: TObject);
var
  i: integer;
begin
  //tutaj z kazdym razem kiedy user zaznacza/odznacza exta odswierzamy liste
  //nie- i skojarzonych z kliperem

  //troche kijowo, mozna by przerobic jak sie bedzie kiedys chcialo :/
  AssociatedExtsVideo := '';
  NotAssociatedExtsVideo := '';
  for i := 0 to LB_Assocs.Count - 1 do
  begin
    if LB_Assocs.Selected[i] then
    begin
      AssociatedExtsVideo := AssociatedExtsVideo + LB_Assocs.Items.Strings[i] + ';';
    end
    else
    begin
      NotAssociatedExtsVideo := NotAssociatedExtsVideo + LB_Assocs.Items.Strings[i] + ';';
    end;
  end;
end;

procedure Tsettingsform.TB_FileIconChange(Sender: TObject);
begin
  //wybieramy ikonke z zasobow dla plikow wideo...
  I_FileIcon.Picture.Icon.Handle := LoadIcon(hInstance, MAKEINTRESOURCE(101 + TB_FileIcon.Position));
end;

procedure Tsettingsform.TB_FileIcon2Change(Sender: TObject);
begin
  //...a tu dla plikow audio
  I_FileIcon2.Picture.Icon.Handle := LoadIcon(hInstance, MAKEINTRESOURCE(101 + TB_FileIcon2.Position));
end;

procedure Tsettingsform.LB_Assocs2Click(Sender: TObject);
var
  i: integer;
begin
  //lustrzana funkcja jak przy LB_Assocs dla wideo
  AssociatedExtsAudio := '';
  NotAssociatedExtsAudio := '';
  for i := 0 to LB_Assocs2.Count - 1 do
  begin
    if LB_Assocs2.Selected[i] then
    begin
      AssociatedExtsAudio := AssociatedExtsAudio + LB_Assocs2.Items.Strings[i] + ';';
    end
    else
    begin
      NotAssociatedExtsAudio := NotAssociatedExtsAudio + LB_Assocs2.Items.Strings[i] + ';';
    end;
  end;
end;

procedure Tsettingsform.B_All2Click(Sender: TObject);
begin
  //wybieramy wsio z listy audio
  LB_Assocs2.SelectAll;
  //i powiazujemy
  LB_Assocs2Click(LB_Assocs);
end;

procedure Tsettingsform.B_None2Click(Sender: TObject);
begin
  //pozbywamy sie wszystkich skojarzen
  LB_Assocs2.ClearSelection;
  LB_Assocs2Click(LB_Assocs);
end;

procedure Tsettingsform.E_AdditionalExts2KeyDown(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin
  //to samo jak przy wideo...
  if Key = VK_RETURN then
  begin
    B_AddExt2.Click;
  end;
end;

procedure Tsettingsform.B_AddExt2Click(Sender: TObject);
var
  i: integer;
begin
  //spr. czy mozne dodac
  if settingsform.CheckExt(E_AdditionalExts2.Text) = false then
  begin
    E_AdditionalExts2.Text := '';
    Exit;
  end;

  //jesli tak to dodajemy do listy
  //i odswiezamy ja
  LB_AdditionalExts2.Items.Add(LowerCase(E_AdditionalExts2.Text));
  AdditionalExtsAudio := '';
  for i := 0 to LB_AdditionalExts2.Count - 1 do
  begin
    AdditionalExtsAudio := AdditionalExtsAudio + LB_AdditionalExts2.Items.Strings[i] + ';';
  end;
  E_AdditionalExts2.Text := '';
end;

procedure Tsettingsform.B_RemoveExt2Click(Sender: TObject);
//lustrzanka jak przy wideo...
var
  i: integer;
begin
  if LB_AdditionalExts2.ItemIndex <> -1 then
  begin
    //odwiazujemy
    RestoreAssoc(LB_AdditionalExts2.Items.Strings[LB_AdditionalExts2.ItemIndex]);
    //i usuwamy z listy
    LB_AdditionalExts2.Items.Delete(LB_AdditionalExts2.ItemIndex);
  end;

  //odswiezamy liste dodatkowych rozszerzen
  AdditionalExtsAudio := '';
  for i := 0 to LB_AdditionalExts2.Count - 1 do
  begin
    AdditionalExtsAudio := AdditionalExtsAudio + LB_AdditionalExts2.Items.Strings[i] + ';';
  end;
end;

end.